<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>

        .box{width:100px;height:100px;position: absolute;left:0;}
        .box1{background: red;top:0;}
        .box2{background: green;top:110px;}
        .box3{background: blue;top:220px;}

    </style>
</head>
<body>
    <div class="box box1"></div>
    <div class="box box2"></div>
    <div class="box box3"></div>
</body>
<script>

    class Drag{
        constructor(ele){
            this.ele = ele;
            this.addEvent();
        }
        addEvent(){
            this.ele.addEventListener("mousedown", this.down.bind(this));
        }
        down(eve){
            this.downE = eve || window.event;
            // 因为将类的方法直接作为事件处理函数设置给了事件，导致this指向出现问题
            // 所以要将事件处理函数内的this指向改变成实例

            // 因为使用了事件监听式绑定事件，删除事件时组要保证删除的事件处理函数和绑定的事件处理函数是同一个
            // 所以要提前将改变了this之后的新函数保存起来，以备绑定和删除时能找到同一个函数

            this.m = this.move.bind(this);
            this.u = this.up.bind(this);
            document.addEventListener("mousemove", this.m)
            document.addEventListener("mouseup", this.u)
        }
        move(eve){
            this.moveE = eve || window.event;
            this.ele.style.left = this.moveE.pageX - this.downE.offsetX + "px";
            this.ele.style.top = this.moveE.pageY - this.downE.offsetY + "px";
        }
        up(){
            document.removeEventListener("mousemove", this.m);
            document.removeEventListener("mouseup", this.u);
        }
    }

    // 通过默认拖拽功能（没有边界限定），继承出一个新的拖拽，添加边界限定功能
    class SmallDrag extends Drag{
        constructor(ele){
            super(ele)
        }
        move(eve){
            this.moveE = eve || window.event;
            let l = this.moveE.pageX - this.downE.offsetX;
            let t = this.moveE.pageY - this.downE.offsetY;
            // 边界限定
            if(l<0) l=0;
            if(t<0) t=0;

            this.ele.style.left = l + "px";
            this.ele.style.top = t + "px";
        }
    }


    const box1 = document.querySelector(".box1");
    const box2 = document.querySelector(".box2");
    const box3 = document.querySelector(".box3");

    new Drag(box1);
    new Drag(box2);

    new SmallDrag(box3);
    
</script>
</html>